#include "StdAfx.h"

#include "Player.h"
#include "camera/Camera.h"
#include "input/InputManager.h"
#include "terrain/Terrain.h"
#include "obj/ObjContainer.h"
#include "obj/PlayerObj.h"
#include "Obj/ControlGroup.h"
#include "core/Game.h"
#include "pathing/PathingManager.h"
#include "graphics/ParticleSystem.h"

Player::Player(Packets::PlayerStartInfo startInfo) : id(startInfo.id), moveSpeed(50.0f), camera(new Camera), 
    terrain(Terrain::getInstance()), input(new InputManager()), army(new Army()), 
    pickingFBO(Game::windowDim, GL_RGBA16), boxSelector(input)
{
	for		( int i = 0; i < 30; ++i ) {
		for (int j = 0; j < 20; ++j) {
			PlayerObj* obj = nullptr;
			if (startInfo.startPos == Packets::PlayerStartInfo::start_north) {
				const float spacing = 3.0f;
				obj = new PlayerObj(glm::vec3(i*spacing+30.0f, 0.0f, j*spacing + 80.0f - startInfo.pos*30.0f), this);
			}
			else if ( startInfo.startPos == Packets::PlayerStartInfo::start_south )
				obj = new PlayerObj(glm::vec3(i*3.0f+10.0f, 1.0f, 10.0f), this);
			else if ( startInfo.startPos == Packets::PlayerStartInfo::start_west )
				obj = new PlayerObj(glm::vec3(i*3.0f+10.0f, 1.0f, 40.0f), this);
			else if ( startInfo.startPos == Packets::PlayerStartInfo::start_east )
				obj = new PlayerObj(glm::vec3(i*3.0f+10.0f, 1.0f, 50.0f), this);

			obj->color = glm::vec4(  
				(static_cast<unsigned char>(startInfo.color >> 24) & 0xFF) / 255.0f,
				(static_cast<unsigned char>(startInfo.color >> 16) & 0xFF) / 255.0f,
				(static_cast<unsigned char>(startInfo.color >> 8) & 0xFF) / 255.0f, 
				1.0);

			army->addObj(obj);
		}
	}
    mouseRect[0] = glm::ivec2(-1, -1);
    mouseRect[1] = glm::ivec2(-1, -1);
}

Player::~Player(){}

void Player::draw(float dt, bool toScreen)
{
	// render the world seen from this player to picking fbo to enable picking 
	ObjContainer::getInstance()->renderForPicking(pickingFBO, camera->getViewMatrix());
    handleInput(dt);
	/*army->update(dt, camera->getViewMatrix());*/
	if (toScreen) {
		// rendering for local player, consider doing this in localplayer derived from player
		ObjContainer::getInstance()->draw(camera->getViewMatrix());
		//PathingManager::getInstance()->draw(camera->getViewMatrix()); // for debugging movement 
		Game::getInstance()->particleSystem->UpdateAndDraw(dt, camera->getViewMatrix());
		boxSelector.draw();
	}
}

void Player::decode(std::vector<unsigned char> & buf) {
	input->decode(buf);
}

void Player::encode(std::vector<unsigned char> & buf) {
	input->encode(buf, 0);
}

void Player::handleInput(float dt)
{
    /* Keyboard move */
    if (input->isKeyPressed(keyboard_w)) 
        camera->moveForward(moveSpeed*dt);
    else if (input->isKeyPressed(keyboard_s)) 
        camera->moveForward(-moveSpeed*dt);
    if (input->isKeyPressed(keyboard_a))
        camera->moveLeft(moveSpeed*dt);
    else if ( input->isKeyPressed(keyboard_d))
        camera->moveLeft(-moveSpeed*dt);

	boxSelector.update(); // tracks any ongoing box selection and updates selection rectangle graphics
	if ( boxSelector.isSelectionReady()) {
		bool shiftHeld = input->isKeyPressed(keyboard_LSHIFT);
		glm::dvec4 box = boxSelector.getSelectionBox();
		if ((box[0]!=box[2] || box[1]!=box[3]))
			army->boxSelect(box, camera->getViewMatrix(), shiftHeld); // pick from local list since selection box only used for self army selection 
		else { // select single obj
			// pick from global list of objs
			Obj* obj = ObjContainer::getInstance()->colorPick(pickingFBO, input->getMousePos());
			
			if (obj) {
				PlayerObj* ownable = dynamic_cast<PlayerObj*>(obj);
				if (ownable) {
					if (ownable->owner == this) { // this player owned
						army->getCG().addSelection(ownable, shiftHeld);
					}
					else { // other player owned
						// add to enemy selection to show info or something 
					}
				} else {
					// non player owned, like a tree
				}
			}
		}
	}
	if ( input->isMouseClicked(mouse_right)) {
		glm::dvec2 mousePos = input->getMousePos();
		glm::vec4 pixel = pickingFBO.sample(glm::dvec2(mousePos.x, Game::windowDim.y - mousePos.y));
		glm::vec2 posOnTerrain = terrain->pick(pixel);
		if ( posOnTerrain != glm::vec2(-1.0f, -1.0f) ) {
			army->move(posOnTerrain);
		}
	}

	if (input->isKeyPressed(keyboard_pluss)) {
		camera->moveVert(moveSpeed*dt);
	} else if (input->isKeyPressed(keyboard_minus)) {
		camera->moveVert(-moveSpeed*dt);
	}

		

    // Handle input for local player and return serialized representation 
    // inputManager->handleInput(dt, nullptr /* &serializedBuffer */);
}

glm::mat4& Player::getViewMatrix() { return camera->getViewMatrix(); }
